
#pragma once

#include "zAdAChar.h"
#include "zacgi.h"
#pragma pack (push, 8)

#ifdef UCGIMATERIAL_IMPL
  #define UCGIMAT_IMPEXP ZSOFT_DLLEXPORT
#else
  #define UCGIMAT_IMPEXP ZSOFT_DLLIMPORT
#endif

class UcGiMaterialColor;
class UcGiMaterialMap;

class UcGiMaterialTraits : public UcGiNonEntityTraits
{
public:
    UCRX_DECLARE_MEMBERS(UcGiMaterialTraits);

    enum IlluminationModel {
        kBlinnShader = 0,
        kMetalShader,
    };

    enum ChannelFlags
    {
        kNone          = 0x00000,
        kUseDiffuse    = 0x00001,
        kUseSpecular   = 0x00002,
        kUseReflection = 0x00004,
        kUseOpacity    = 0x00008,
        kUseBump       = 0x00010,
        kUseRefraction = 0x00020,
        kUseNormalMap  = 0x00040,
        kUseAll        = (kUseDiffuse | kUseSpecular | kUseReflection
                            | kUseOpacity | kUseBump | kUseRefraction
                            | kUseNormalMap),
    };

    enum Mode {
        kRealistic = 0,
        kAdvanced,
    };

	enum LuminanceMode
	{
		kSelfIllumination = 0,
		kLuminance,
	};

	enum NormalMapMethod
	{
		kTangentSpace
	};

	enum GlobalIlluminationMode
	{
		kGlobalIlluminationNone,
		kGlobalIlluminationCast,
		kGlobalIlluminationReceive,
		kGlobalIlluminationCastAndReceive
	};

	enum FinalGatherMode
	{
		kFinalGatherNone,
		kFinalGatherCast,
		kFinalGatherReceive,
		kFinalGatherCastAndReceive
	};
    virtual void setAmbient     (const UcGiMaterialColor & color)   = 0;
    virtual void setDiffuse     (const UcGiMaterialColor & color, 
                                 const UcGiMaterialMap & map)       = 0;
    virtual void setSpecular    (const UcGiMaterialColor & color, 
                                 const UcGiMaterialMap & map,
                                 double dGloss)                     = 0;
    virtual void setReflection  (const UcGiMaterialMap & map)       = 0;
    virtual void setOpacity     (double dPercentage, 
                                 const UcGiMaterialMap & map)       = 0;
    virtual void setBump        (const UcGiMaterialMap & map)       = 0;
    virtual void setRefraction  (double dIndex, 
                                 const UcGiMaterialMap & map)       = 0;
    virtual void setTranslucence(double value)                      = 0;
    virtual void setSelfIllumination(double value)                  = 0;
    virtual void setReflectivity(double value)                      = 0;
    virtual void setIlluminationModel(IlluminationModel model)      = 0;
    virtual void setChannelFlags(ChannelFlags flags)                = 0;
    virtual void setMode(Mode value)                                = 0;
    virtual void ambient        (UcGiMaterialColor & color) const   = 0;
    virtual void diffuse        (UcGiMaterialColor & color, 
                                 UcGiMaterialMap & map) const       = 0;
    virtual void specular       (UcGiMaterialColor & color, 
                                 UcGiMaterialMap & map,
                                 double & dGloss) const             = 0;
    virtual void reflection     (UcGiMaterialMap & map) const       = 0;
    virtual void opacity        (double & dPercentage, 
                                 UcGiMaterialMap & map) const       = 0;
    virtual void bump           (UcGiMaterialMap & map) const       = 0;
    virtual void refraction     (double & dIndex, 
                                 UcGiMaterialMap & map) const       = 0;
    virtual double translucence() const                             = 0;
    virtual double selfIllumination() const                         = 0;
    virtual double reflectivity() const                             = 0;
    virtual IlluminationModel illuminationModel() const             = 0;
    virtual ChannelFlags channelFlags() const                       = 0;
    virtual Mode mode() const                                       = 0;

	virtual void setColorBleedScale(double value)                   = 0;
    virtual void setIndirectBumpScale(double value)                 = 0;
    virtual void setReflectanceScale(double value)                  = 0;
    virtual void setTransmittanceScale(double value)                = 0;
    virtual void setTwoSided(bool value)                            = 0;
    virtual void setLuminanceMode(LuminanceMode value)              = 0;
    virtual void setLuminance(double value)                         = 0;
    virtual void setNormalMap(const UcGiMaterialMap & map,
                              NormalMapMethod method,
                              double strength)                      = 0;
    virtual void setGlobalIllumination(GlobalIlluminationMode mode) = 0;
    virtual void setFinalGather(FinalGatherMode mode)               = 0;
    virtual double colorBleedScale() const                          = 0;
    virtual double indirectBumpScale() const                        = 0;
    virtual double reflectanceScale() const                         = 0;
    virtual double transmittanceScale() const                       = 0;
    virtual bool   twoSided() const                                 = 0;
    virtual LuminanceMode luminanceMode() const                     = 0;
    virtual double luminance() const                                = 0;
    virtual void normalMap(UcGiMaterialMap & map,
                           NormalMapMethod &method,
                           double &strength) const                  = 0;
    virtual GlobalIlluminationMode globalIllumination() const       = 0;
    virtual FinalGatherMode finalGather() const                     = 0;
};

class UcGiImpMaterialColor;

class UcGiMaterialColor: public UcRxObject
{
public:
    UCRX_DECLARE_MEMBERS(UcGiMaterialColor);

    enum Method {
        kInherit = 0,
        kOverride,     
    };

    UCGIMAT_IMPEXP static const UcGiMaterialColor kNull;

    UcGiMaterialColor             (void);
    virtual ~UcGiMaterialColor    (void);

    UcGiMaterialColor             (const UcGiMaterialColor &matColor);
    UcGiMaterialColor & operator= (const UcGiMaterialColor &matColor);
	bool                operator==(const UcGiMaterialColor &matColor)const;

    virtual void set       (const UcGiMaterialColor &matColor);
    virtual void setMethod (Method method);
    virtual void setFactor (double dFactor);
    virtual void setColor  (const UcCmEntityColor& color);

    virtual Method                  method (void) const;
    virtual double                  factor (void) const;
    virtual const UcCmEntityColor & color  (void) const;

private:
    UcGiImpMaterialColor * mpUcGiImpMaterialColor;
};

class UcGiMaterialTexture : public UcRxObject
{
public:
	UCRX_DECLARE_MEMBERS(UcGiMaterialTexture);
	virtual bool operator==(const UcGiMaterialTexture & texture)const;
protected:
};

inline bool UcGiMaterialTexture::operator==(const UcGiMaterialTexture & texture) const {
        return (texture.isA() == isA());
}

class UcGiImageTexture : public UcGiMaterialTexture
{
public:
	UCRX_DECLARE_MEMBERS(UcGiImageTexture);
};

class UcGiImpImageFileTexture;

class UcGiImageFileTexture : public UcGiImageTexture
{
	friend class UcGiImpImageFileTexture;
public:
	UCRX_DECLARE_MEMBERS(UcGiImageFileTexture);

	UcGiImageFileTexture             (void);
	virtual ~UcGiImageFileTexture    (void);

	UcGiImageFileTexture             (const UcGiImageFileTexture &texture);
	UcGiImageFileTexture & operator= (const UcGiImageFileTexture &texture);
	virtual bool operator==(const UcGiMaterialTexture & texture) const;

	virtual Ucad::ErrorStatus copyFrom(const UcRxObject* other);

	virtual void                setSourceFileName (const ZTCHAR * fileName);
	virtual const ZTCHAR *      sourceFileName    (void) const;
private:
	UcGiImpImageFileTexture * mpUcGiImpImageFileTexture;
};

class UcGiProceduralTexture : public UcGiMaterialTexture
{
public:
	UCRX_DECLARE_MEMBERS(UcGiProceduralTexture);

	enum Type
	{
		kWood = 0,
		kMarble,
		kGeneric,
	};
	virtual Type type()const = 0;
};

class UcGiGenericTexture : public UcGiProceduralTexture
{
public:
	UCRX_DECLARE_MEMBERS(UcGiGenericTexture);

	UcGiGenericTexture              (void);
	virtual ~UcGiGenericTexture      (void);

	UcGiGenericTexture              (const UcGiGenericTexture &texture);
	UcGiGenericTexture & operator=  (const UcGiGenericTexture &texture);
	virtual bool         operator== (const UcGiMaterialTexture &texture) const;

	virtual Ucad::ErrorStatus copyFrom(const UcRxObject* other);

	void            setDefinition   (const UcGiVariant& definition);
	UcGiVariant     definition      (void) const;
	void            definition      (UcGiVariant*& pDefinition);
	virtual Type type()const {return kGeneric;}
protected:
	UcGiVariant     m_definition;
};

class UcGiImpWoodTexture;

class UcGiWoodTexture : public UcGiProceduralTexture
{
	friend class UcGiImpWoodTexture;
public:
	UCRX_DECLARE_MEMBERS(UcGiWoodTexture);

	UcGiWoodTexture             (void);
	virtual ~UcGiWoodTexture    (void);

	UcGiWoodTexture             (const UcGiWoodTexture &texture);
	UcGiWoodTexture & operator= (const UcGiWoodTexture &texture);
	virtual bool      operator==(const UcGiMaterialTexture & texture) const;

	virtual Ucad::ErrorStatus copyFrom(const UcRxObject* other);

	virtual void setColor1      (const UcGiMaterialColor &woodColor1);
	virtual const UcGiMaterialColor & color1  (void) const;

	virtual void setColor2      (const UcGiMaterialColor &woodColor2);
	virtual const UcGiMaterialColor & color2  (void) const;

	virtual void setRadialNoise (double radialNoise);
	virtual double radialNoise  (void) const;

	virtual void setAxialNoise  (double axialNoise);
	virtual double axialNoise   (void) const;

	virtual void setGrainThickness  (double grainThickness);
	virtual double grainThickness   (void) const;
	virtual Type type()const {return kWood;}
private:
	UcGiImpWoodTexture * mpUcGiImpWoodTexture;
};

class UcGiImpMarbleTexture;

class UcGiMarbleTexture : public UcGiProceduralTexture
{
	friend class UcGiImpMarbleTexture;
public:
	UCRX_DECLARE_MEMBERS(UcGiMarbleTexture);

	UcGiMarbleTexture             (void);
	virtual ~UcGiMarbleTexture    (void);

	UcGiMarbleTexture             (const UcGiMarbleTexture &texture);
	UcGiMarbleTexture & operator= (const UcGiMarbleTexture &texture);
	virtual bool        operator==(const UcGiMaterialTexture & texture) const;

	virtual Ucad::ErrorStatus copyFrom(const UcRxObject* other);

	virtual void setStoneColor     (const UcGiMaterialColor &stoneColor);
	virtual const UcGiMaterialColor & stoneColor  (void) const;

	virtual void setVeinColor      (const UcGiMaterialColor &veinColor);
	virtual const UcGiMaterialColor & veinColor  (void) const;

	virtual void setVeinSpacing    (double veinSpacing);
	virtual double veinSpacing     (void) const;

	virtual void setVeinWidth      (double veinWidth);
	virtual double veinWidth       (void) const;
	virtual Type type()const {return kMarble;}
private:
	UcGiImpMarbleTexture * mpUcGiImpMarbleTexture;
};

class UcGiMapper;
class UcGiImpMaterialMap;

class UcGiMaterialMap: public UcRxObject 
{
public:
    UCRX_DECLARE_MEMBERS(UcGiMaterialMap);

    enum Source {
        kScene = 0,
        kFile,
        kProcedural
    };

	enum Filter 
	{
		kFilterDefault = 0,
		kFilterNone
	};

	UCGIMAT_IMPEXP Ucad::ErrorStatus   setFilter   (Filter filter);
	UCGIMAT_IMPEXP Filter              filter      (void) const;
    UCGIMAT_IMPEXP static const UcGiMaterialMap kNull;

    UcGiMaterialMap             (void);
    virtual ~UcGiMaterialMap    (void);

    UcGiMaterialMap             (const UcGiMaterialMap &matMap);
    UcGiMaterialMap & operator= (const UcGiMaterialMap &matMap);
    bool              operator==(const UcGiMaterialMap &matMap)const;
    virtual void set               (const UcGiMaterialMap &matMap);
    virtual void setSource         (Source source);
    ZSOFT_DEPRECATED virtual void setSourceFileName (const ZTCHAR * fileName);
    virtual void setTexture        (const UcGiMaterialTexture * pTexture);
    virtual void setBlendFactor    (double blendFactor);
    virtual void setMapper         (const UcGiMapper &mapper);

    virtual Source                  source         (void) const;
    ZSOFT_DEPRECATED virtual const ZTCHAR * sourceFileName (void) const;
    virtual const UcGiMaterialTexture *  texture   (void) const;
    virtual double                  blendFactor    (void) const;
    virtual const UcGiMapper &      mapper         (void) const;

private:
    UcGiImpMaterialMap * mpUcGiImpMaterialMap;
};

class UcGiImpMapper;

class UcGiMapper: public UcRxObject 
{
public:
	UCRX_DECLARE_MEMBERS(UcGiMapper);

    enum Projection {
        kInheritProjection = 0,
        kPlanar,
        kBox,
        kCylinder,
        kSphere
    };

    enum Tiling {
        kInheritTiling = 0,
        kTile,
        kCrop,
        kClamp,
        kMirror,
    };

    enum AutoTransform {
        kInheritAutoTransform = 0x0,
        kNone                 = 0x1,
        kObject               = 0x2,
        kModel                = 0x4
    };

    UCGIMAT_IMPEXP static const UcGiMapper kIdentity;

    UcGiMapper             (void);
    virtual ~UcGiMapper    (void);

    UcGiMapper             (const UcGiMapper &mapper);
    UcGiMapper & operator= (const UcGiMapper &mapper);
    bool         operator==(const UcGiMapper &mapper) const;
    bool         operator!=(const UcGiMapper &mapper) const
    {
        return !(*this == mapper);
    };
    virtual                  void set               (const UcGiMapper &mapper);
    virtual                  void setProjection     (Projection projection);
    virtual                  void setAutoTransform  (AutoTransform autoTransform);
    virtual                  void setTransform      (const UcGeMatrix3d &transform);
    virtual                     Projection             projection    (void) const;
	virtual                     AutoTransform          autoTransform (void) const;
    virtual                     const UcGeMatrix3d&    transform     (void) const;
    void        setUTiling        (Tiling tiling);
    void        setVTiling        (Tiling tiling);
    Tiling      uTiling           (void) const;
    Tiling      vTiling           (void) const;
private:
	UcGiImpMapper * mpUcGiImpMapper;
};

#pragma pack (pop)
